package org.lora.core.jdbctx.impl;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.TransactionException;
import org.lora.core.jdbctx.TransactionSynchronizationManager;

/**
 * <p>
 * 类名:MapperTransaction
 * </p>
 * 描述:<br>
 * 创建时间:2016年11月23日 下午3:11:22<br>
 * 
 * @author Bladnir@outlook.com<br>
 *         修改历史:<br>
 *         2016年11月23日 Bladnir 创建<br>
 */
public class MapperTransaction implements org.apache.ibatis.transaction.Transaction {

	private static final Log log = LogFactory.getLog(MapperTransaction.class);

	protected volatile Connection connection;
	protected volatile DataSource dataSource;
	protected volatile TransactionIsolationLevel level;
	protected volatile boolean autoCommmit;

	/**
	 * 构造方法 只使用这种方式来构建对象
	 * 
	 * @param ds
	 * @param desiredLevel
	 * @param desiredAutoCommit
	 */
	public MapperTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
		this.dataSource = ds;
		this.level = desiredLevel;
		this.autoCommmit = desiredAutoCommit;
	}

	/**
	 * 构造方法
	 *
	 * @param connection
	 */
	public MapperTransaction(Connection connection) {
		// 不使用这种方式来构建此对象
	}

	@Override
	public Connection getConnection() throws SQLException {

		if (connection == null) {
			openConnection();
		}

		return connection;
	}

	@Override
	public void commit() throws SQLException {
		TransactionSynchronizationManager.commitConnection();
	}

	@Override
	public void rollback() throws SQLException {
		TransactionSynchronizationManager.rollbackConnection();
	}

	@Override
	public void close() throws SQLException {
		TransactionSynchronizationManager.closeConnection();
	}

	protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
		try {
			if (connection.getAutoCommit() != desiredAutoCommit) {
				connection.setAutoCommit(desiredAutoCommit);
			}
		} catch (SQLException e) {
			throw new TransactionException("Error configuring AutoCommit.  "
					+ "Your driver may not support getAutoCommit() or setAutoCommit(). " + "Requested setting: " + desiredAutoCommit
					+ ".  Cause: " + e, e);
		}
	}

	protected void openConnection() throws SQLException {

		connection = TransactionSynchronizationManager.getConnection(dataSource);

		if (level != null) {
			connection.setTransactionIsolation(level.getLevel());
		}
		setDesiredAutoCommit(autoCommmit);
	}

}
